package com.dayu.finecomm.dsc.net;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioDatagramChannel;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GenericFutureListener;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.dayu.finecomm.dsc.DSCInterface;
import com.dayu.finecomm.dsc.handler.DSCUdpHandler;

/**
 * 创建UDP Listen Socket
 * @author hddz
 * @since 2017-07-26 16:28:30
 * @version V1.0
 *
 */
public class DSCUdpServer extends DSCSocketServer {
	static Logger LOGGER = LoggerFactory.getLogger(DSCUdpServer.class);
	
	/**
	 * 设置最大buffer大小为6M
	 */
	private static final int DSC_RECV_BUFF_MAX_SIZE = 6 * 1024 * 1024;
	
	/**
	 * EventLoopGroup
	 */
	EventLoopGroup mGroup = null;
	
	public DSCUdpServer(String strHost, int nPort, DSCInterface callback) {
		if (null != strHost) {
			mHost = new String(strHost);
		}
		
		mPort = nPort;
		
		mCallback = callback;
	}
	
	/**
	 * 启动监听UDP Socket
	 * @return ChannelFuture
	 * @throws InterruptedException
	 */
	@Override
	public ChannelFuture bootstrap() throws InterruptedException {	
		mGroup = new NioEventLoopGroup();

		Bootstrap b = new Bootstrap();
		b.option(ChannelOption.SO_RCVBUF, DSC_RECV_BUFF_MAX_SIZE);
		b.channel(NioDatagramChannel.class).group(mGroup);

		b.handler(new ChannelInitializer<NioDatagramChannel>() {  
            @Override
            public void initChannel(NioDatagramChannel ch) throws Exception {  
                ChannelPipeline pipeline = ch.pipeline();
                
                pipeline.addLast(new DSCUdpHandler(mCallback));
            }
		});

		ChannelFuture f = null;
		if (null == mHost || true == mHost.isEmpty()) {
			f = b.bind(mPort).sync();
		} else {
			f = b.bind(mHost, mPort).sync();
		}
		
		ChannelFuture cf = f.channel().closeFuture();

		cf.addListener(new GenericFutureListener<Future<? super Void>>() {

			@Override
			public void operationComplete(Future<? super Void> future)
					throws Exception {
				mGroup.shutdownGracefully();
			}
		});

		return cf;
	}
	
	/**
	 * 退出
	 */
	@Override
	public void shutdown() {
		if (null != mGroup) {
			mGroup.shutdownGracefully();
			mGroup = null;
		}
	}
}
